﻿// Copyright (C) 2014 Can Batu Erdem
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using Cyrene.Strategy;
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Text;

namespace Cyrene.Serializer
{
    internal static class ExceptionSerializer
    {
        internal static string Serialize(TableGeneratorStrategy tableGenerator, Exception exception)
        {
            if (exception == null)
            {
                throw new ArgumentNullException("exception");
            }

            StringBuilder sb = new StringBuilder();
            sb.Append(tableGenerator.GenerateTableHeader("Exception"));
            NameValueCollection collection = new NameValueCollection();
            collection.Add("Type", exception.GetType().FullName);
            collection.Add("Message", exception.Message);
            collection.Add("Source", exception.Source);
            collection.Add("Target Site", exception.TargetSite == null ? string.Empty : exception.TargetSite.ToString());
            collection.Add("Help Link", exception.HelpLink ?? string.Empty);
            sb.Append(tableGenerator.GenerateTableContent(collection));
            sb.Append(SerializeData(tableGenerator, exception.Data));
            sb.Append(SerializeStackTrace(tableGenerator, exception.StackTrace));
            sb.Append(tableGenerator.GenerateTableFooter());

            if (exception.InnerException != null)
            {
                sb.Append(Serialize(tableGenerator, exception.InnerException));
            }

            return sb.ToString();
        }

        private static string SerializeData(TableGeneratorStrategy tableGenerator, IDictionary data)
        {
            if (data.Count > 0)
            {
                NameValueCollection collection = new NameValueCollection();
                foreach (DictionaryEntry de in data)
                {
                    collection.Add(de.Key.ToString(), de.Value == null ? "(NULL)" : de.Value.ToString());
                }

                return tableGenerator.GenerateInlineHeader("Data") + tableGenerator.GenerateTableContent(collection);
            }

            return string.Empty;
        }

        private static string SerializeStackTrace(TableGeneratorStrategy tableGenerator, string stackTrace)
        {
            if (!string.IsNullOrWhiteSpace(stackTrace))
            {
                return tableGenerator.GenerateInlineHeader("Stack Trace") + tableGenerator.GenerateTableContentSingleColumn(stackTrace.Split(new char[] { '\n' }));
            }

            return string.Empty;
        }
    }
}
